﻿using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using System.Text;
using ConsoleApp.Model.Option;
using Microsoft.IdentityModel.Tokens;

namespace ConsoleApp.Middleware;

public class JwtMiddleware
{
    private readonly RequestDelegate _next;
    private readonly JwtOpt _authOptions;

    public JwtMiddleware(RequestDelegate next, IConfiguration configuration)
    {
        _next = next;
        _authOptions = configuration.GetSection("JwtOpt").Get<JwtOpt>();
    }

    public async Task Invoke(HttpContext context)
    {
        var token = context.Request.Headers["Authorization"].FirstOrDefault()?.Split(" ").Last()
                    ?? context.Request.Headers["token"].FirstOrDefault()
                    ?? context.Request.Query["Token"].FirstOrDefault()
                    ?? context.Request.Cookies["Token"];
        if (token != null)
            AttachUserToContext(context, token);
        await _next(context);
    }

    private void AttachUserToContext(HttpContext context, string token)
    {
        try
        {
            var tokenHandler = new JwtSecurityTokenHandler();
            byte[]? key = Encoding.ASCII.GetBytes(_authOptions.SecurityKey);
            tokenHandler.ValidateToken(token, new TokenValidationParameters
            {
                ValidateIssuerSigningKey = true,
                IssuerSigningKey = new SymmetricSecurityKey(key),
                ValidateIssuer = true,
                ValidateAudience = true,
                ValidateLifetime = true,
                ValidIssuer = _authOptions.Issuer,
                ValidAudience = _authOptions.Audience,
                ClockSkew = TimeSpan.Zero
            }, out SecurityToken validatedToken);
            var jwtToken = (JwtSecurityToken)validatedToken;
            var user = jwtToken.Claims.First(x => x.Type == "User").Value;
            var claimsIdentity = new ClaimsIdentity(new Claim[] { new Claim("User", jwtToken.Claims.First(x => x.Type == "User").Value) });
            Thread.CurrentPrincipal = new ClaimsPrincipal(claimsIdentity);
            context.Items["User"] = user;
        }
        catch
        {

        }
    }
}